#!/usr/bin/env python
# coding: utf-8
import re
import os
import time
import datetime
import string
from onshs.ne.tnxxx.tnxxxcfg_basecase import *

log_node_prefix = "utDMemTrac"
log_node_summary = log_node_prefix+r"_summary"
log_node_fail = log_node_prefix+r"_fail"
log_node_success = log_node_prefix+r"_success"
log_node_warning = log_node_prefix+r"_warning"

log_file_notexisted_fail = "the file:%s isn't existed\n"
log_connect_fail = "connect ip:%s count:%d failed\n"
log_memory_trace_count_fail = "get ip:%s slot:%s memory trace count failed\n"
log_memory_trace_count_success = "get ip:%s slot:%s memory trace count success\n"
log_analyze_memory_trace_success = "show key:%s trend:%s success\n"

log_summary_success = "ip:%s slot:%s count:%d success"
log_summary_fail = "ip:%s slot:%s count:%d failed"


class TestCase(TnxxxCfg_BaseCase):
    """
    TestCase
    """
    OPTIONS = [
        {
            'opt' : '--cfgfile',
            'dest': 'cfgfile',
            'metavar' : 'CFGFILE',
            'help' : 'the file of ip list configuration',
            'required' : False,
            'default' : "ip.txt"
        },
        {
            'opt' : '--interval',
            'dest': 'interval',
            'metavar' : 'INTERVAL',
            'help' : 'the interval(min) of query memory allocate statistics, the range is [3,60*24]',
            'required' : False,
            'default' : 10
        },
        {
            'opt' : '--count',
            'dest': 'count',
            'metavar' : 'COUNT',
            'help' : 'the count of query memory allocate statistics, the range is [2,30]',
            'required' : False,
            'default' : 8
        }, 
    ]     
    
    def info_init(self):
        self.info_dic = {}     
              
        return True 
    
    #以node为关键字，把信息保存到info_dic[node]中。
    def info_show(self, node, info):        
        if not self.info_dic.has_key(node):
            self.info_dic[node] = ""
        self.info_dic[node] += info + '\n'        
        return True    
            
    def info_file_save(self):
        path = os.getcwd()+'//'
        
        for node in self.info_dic:
            info_list = open(path+node+'_'+self.worktime+'.txt','a')            
            info_list.write(self.info_dic[node])
            info_list.close()
            
        return True
    
    def get_iplist(self):
        iplist_filted = []                
        if os.path.isfile(os.getcwd()+r'/'+ self.iplistfile):
            iplist = open(os.getcwd()+r'/'+ self.iplistfile)            
        else:
            self.info_show(log_node_fail, log_file_notexisted_fail%(self.iplistfile))            
            return iplist_filted 
        
        for line in iplist:
            if re.match(r'^\s*$', line) is not None : continue # 忽略空白行
            if re.match(r'^\s*#', line) is not None : continue # 忽略注释行            
            iplist_filted.append(line.strip('\n'))        
            
        iplist.close()
        
        return iplist_filted        
    
        
    def get_slotlist_from_cardtype(self, cardtype_list):
        """
        cardtype_list = [cardtype(str),...]       
        """
        
        query_slotlist = [3,4,5,6,7,8]
        slotlist = []
                    
        rtn = self.tnxxx.send_rtn_str("show card", self.get_ne_ip(0), 0, CLI_PORT)
        card_info_list = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?stat:\s+\w+\s+(?:--More--\s+)?Card:\s+(\w+)\s+", rtn, re.I)
        
        for card_info in card_info_list:
            slot = int(card_info[0])
            if slot not in query_slotlist : continue            
           
            card_name = card_info[1].upper()
            
            for cardtype in cardtype_list:                
                if cardtype == card_name:
                    slotlist.append(slot)
                    break
            else:
                continue        
            
        return slotlist
              
    def get_memory_trace(self,slot,number):        
        cmd = r'mem -m 10000000'        
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), slot, MTN_PORT)
        
        trace_list = re.findall(r"(0x\w+\s+0x\w+\s+0x\w+\s+0x\w+\s+0x\w+)", rtn_str)
        trace_count_list = re.findall(r"print cnt:(\d+)", rtn_str)
        trace_count = 0
        if [] != trace_count_list:
            trace_count = trace_count_list[0]
       
        for trace in trace_list:
            trace_key = "ip:"+self.get_ne_ip(0)+' slot:'+str(slot)+' '+trace
            if not self.memory_trace_dic.has_key(trace_key):
                self.memory_trace_dic[trace_key] = [0]*(self.count)
                
            self.memory_trace_dic[trace_key][number]+=1
        
        count_number = 0
        for trace_key in self.memory_trace_dic.keys():
            if [] != re.findall("ip:"+self.get_ne_ip(0)+' slot:'+str(slot),trace_key):
                count_number += self.memory_trace_dic[trace_key][number]
        
        if (int(trace_count) == count_number) and (0 != count_number):
            self.info_show(log_node_success, log_memory_trace_count_success%(self.get_ne_ip(0),slot))
            return True
        else:
            self.info_show(log_node_fail, log_memory_trace_count_fail%(self.get_ne_ip(0),slot))            
            return False                 
    
    def analyze_memory_trace(self):
        for trace_key in self.memory_trace_dic.keys():
            self.analyze_memory_trace_dic[trace_key] = ""
            for i in range(len(self.memory_trace_dic[trace_key])-1):
                self.analyze_memory_trace_dic[trace_key] += str(self.memory_trace_dic[trace_key][i+1]-self.memory_trace_dic[trace_key][i])+'_'
            
            self.info_show(log_node_success, log_analyze_memory_trace_success%(trace_key,self.analyze_memory_trace_dic[trace_key]))
            
            #find out the all tread list, and add trend list = all trend list - noadd trend list 
            trend_list = re.findall("[-\d]+",self.analyze_memory_trace_dic[trace_key])
            sum = 0
            for trend in trend_list:
                sum += int(trend)
            noadd_trend_list = re.findall("[0-]+",self.analyze_memory_trace_dic[trace_key])
            add_count = len(trend_list)-len(noadd_trend_list)
            if float(add_count)/float(self.count-1) >= 0.8 and sum > 0:
                self.info_show(log_node_warning, log_analyze_memory_trace_success%(trace_key,self.analyze_memory_trace_dic[trace_key]))
                            
    def _execute(self):                        
        self.info_init()
        
        worktime = str(datetime.datetime.now())
        self.worktime = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.iplistfile = self.options.cfgfile
        self.interval = int(self.options.interval)
        self.count = int(self.options.count)
        self.work_path = os.getcwd()
        self.memory_trace_dic = {}
        self.analyze_memory_trace_dic = {}
        
        ip_list = self.get_iplist()         
        
        for number in range(self.count):
            for ip in ip_list:            
                self.set_ne_ip(0, ip)  
                self.master_opca = 0                
                self.tnxxx.disconnect()
                
                slot_list = self.get_slotlist_from_cardtype(['OPCA', 'N64F01', 'N16F01'])
                if [] == slot_list:
                    self.info_show(log_node_summary, log_connect_fail%(self.get_ne_ip(0),number+1))                    
                    continue
                                            
                for slot in slot_list:   
                    if False == self.get_memory_trace(slot,number):
                        self.info_show(log_node_summary, log_summary_fail%(self.get_ne_ip(0),slot,number+1))                        
                    else:
                        self.info_show(log_node_summary, log_summary_success%(self.get_ne_ip(0),slot,number+1))
            time.sleep(self.interval*60)
        
        self.analyze_memory_trace()
           
        worktime = str(datetime.datetime.now())
        self.worktime_end = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.info_show(log_node_summary, "The utDmemTrac operation begin time %s "%(self.worktime))
        self.info_show(log_node_summary, "The utDmemTrac operation end time %s "%(self.worktime_end))                 
        
        self.info_file_save() 
        return True
    
if __name__ == "__main__" :
    case = TestCase()
    case.execute()